﻿using SignalBox.Core.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace SignalBox.Core.Model.Graph
{
    public class SignalGraph
    {
        private TrackLayout _trackLayout;
        private LayoutGraph _layoutGraph;

        public SignalGraph(TrackLayout trackLayout)
        {
            _trackLayout = trackLayout;
            _layoutGraph = new LayoutGraph(trackLayout, false);


            //_layoutGraph.WriteDebug();

            buildGraph();
        }

        private List<SignalNode> signals;

        public List<SignalNode> Signals
        {
            get { return signals; }
        }

        private void buildGraph()
        {

            signals = new List<SignalNode>();

            for (int x = 0; x < _trackLayout.Cols; x++)
            {
                for (int y = 0; y < _trackLayout.Rows; y++)
                {
                    TrackCell tc = _trackLayout.getCell(x, y);

                    if (tc != null)
                    {
                        if (tc.TrackCellType.Category == "SIGNAL")
                        {
                            SignalNode sn = findNodeAt(tc);
                            if (sn == null)
                            {
                                sn = new SignalNode(tc);
                                signals.Add(sn);
                                findNextSignal(sn);    
                            }

                            
                        }
                    }
                }
            }

        }

        private SignalNode findNodeAt(TrackCell tc)
        {

            foreach (SignalNode sn in signals)
            {
                if (sn.Cell == tc)
                    return sn;
            }

            return null;
        }

        private void findNextSignal(SignalNode sn)
        {
            TrackCell current = sn.Cell;
            GraphNode next = null;
            GraphNode gNode = _layoutGraph.findNode(current);
            DIRECTION dir = current.TrackCellType.GetSignalDirectionOutput(current.TrackCellType.TheTrackCellType);

            next = gNode.GetNextNode(dir);

            while (next != null && (next.Cell.TrackCellType.Category != "SIGNAL" /*|| (next.Cell.TrackCellType.Category == "SIGNAL" && next.Cell.TrackCellType.GetSignalDirectionOutput(next.Cell.TrackCellType.TheTrackCellType) != dir)*/) && next.Cell.TrackCellType.Category != "ENTRYEXIT")
            {
                if (next.Cell.Occupied)
                    sn.Occupied = true;
                dir = next.GetNextDirectionFromInput(RouteFinding.GetOppositeDirection(dir));
                next = next.GetNextNode(dir);
                
                //_layoutGraph.WriteDebug();
            }

            if (next == null) return;

            SignalNode sigNode = findNodeAt(next.Cell);
            if (sigNode == null)
            {
                sigNode = new SignalNode(next.Cell);
                sigNode.PreviousSignal = sn;
                sn.NextSignal = sigNode;
                signals.Add(sigNode);
                findNextSignal(sigNode);
            }
        }

    }
}
